#ifndef EMS_PROTOCOL_MODBUS_PROTOCOL_MANAGER_H
#define EMS_PROTOCOL_MODBUS_PROTOCOL_MANAGER_H

#include "protocol/ProtocolInterface.h"
#include "utils/Json.h"

#include <string>
#include <vector>
#include <map>
#include <memory>

namespace ems {
namespace protocol {

enum class EByteOrder {
    BIG,
    LITTLE
};

struct DataPoint {
    std::string name;
    std::string chineseName;
    uint16_t address;
    RegisterType registerType;
    uint16_t length;
    DataType dataType;
    EByteOrder byteOrder;
    double coefficient;
    double offset;
    std::string unit;
    double minValue;
    double maxValue;
    int decimalPlaces;
    std::map<int, std::string> bitField;
    std::string description;
    std::string section;          // 章节信息
    std::string category;         // 数据类别
    std::string deviceCategory;   // 设备类别 (pcs/bms/alarm)
    bool writable;               // 是否可写

    DataPoint() : address(0), registerType(RegisterType::HOLDING_REGISTER), length(1),
                  dataType(DataType::UINT16), byteOrder(EByteOrder::BIG),
                  coefficient(1.0), offset(0.0), minValue(0.0), maxValue(0.0),
                  decimalPlaces(0), writable(false) {}
};

struct ProtocolConfig {
    std::string vendor;
    std::string model;
    std::string version;
    std::string description;
    int defaultSlaveId;
    int defaultTimeout;
    int retryTimes;
    int retryInterval;
    std::vector<DataPoint> dataPoints;
    std::map<std::string, std::string> functionCodes;
    std::map<std::string, std::string> errorCodes;
    
    ProtocolConfig() : defaultSlaveId(1), defaultTimeout(3000), retryTimes(3), retryInterval(1000) {}
};

class ProtocolManager {
public:
    ProtocolManager();
    ~ProtocolManager();
    
    bool loadProtocol(const std::string& protocolFile);
    
    double convertRawValue(const std::string& dataPointName, const std::vector<uint16_t>& rawData) const;
    bool parseRawData(const DataPoint& dataPoint, const std::vector<uint16_t>& rawData, double& value) const;
    
    const ProtocolConfig& getConfig() const { return config_; }
    const DataPoint* getDataPoint(const std::string& name) const;
    std::vector<std::string> getDataPointNames() const;

private:
    ProtocolConfig config_;
    std::map<std::string, size_t> dataPointIndex_;
    
    bool parseProtocolInfo(const utils::Json& json);
    bool parseConnection(const utils::Json& json);
    bool parseDataPoints(const utils::Json& json);
    bool parseFunctionCodes(const utils::Json& json);
    bool parseErrorCodes(const utils::Json& json);
    
    DataPoint parseDataPoint(const utils::Json& json) const;
    DataType stringToDataType(const std::string& str) const;
    RegisterType stringToRegisterType(const std::string& str) const;
    EByteOrder stringToByteOrder(const std::string& str) const;
    RegisterType getFunctionCodeRegisterType(int functionCode) const;
    void parseRangeString(const std::string& rangeStr, double& minValue, double& maxValue) const;
    
    uint64_t rawDataToUint64(const std::vector<uint16_t>& rawData, DataType dataType, EByteOrder byteOrder) const;
    int64_t rawDataToInt64(const std::vector<uint16_t>& rawData, DataType dataType, EByteOrder byteOrder) const;
    double rawDataToFloat(const std::vector<uint16_t>& rawData, DataType dataType, EByteOrder byteOrder) const;
};

}  // namespace protocol
}  // namespace ems

#endif  // EMS_PROTOCOL_MODBUS_PROTOCOL_MANAGER_H